package com.qs.javame.thread.think;

import java.util.concurrent.TimeUnit;

/**
 * 测试：线程等待超时模式
 * 要点：
 *  1、超时时间计算：
 *  long future = System.currentTimeMillis() + timeout;
 *  long remain = future - System.currentTimeMillis();
 *  2、while循环判断超时时间结束及结束前result是否获取到结果；
 *  3、while循环中在等待超时时间范围内，wait(remain)让线程进入等待；
 */
public class TestDemo3 {

    public static void main(String[] args) {
        Result r = new Result();

        //开始线程，用来获取result的值，在指定的5s等待时间内，如果result依旧没获取到值或者等待超时了，都将返回null
        Thread thread = new Thread(() -> {
            String result = r.getResult(5 * 1000);
        }, "Thread-0");

        thread.start();


        //开启一个线程，用来设置result的值
        Thread thread2 = new Thread(() -> {
            //线程休眠5s，则thread-0线程会超时返回result=null
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + "-开始设置result的值");
            r.setResult("this is result value");
        }, "Thread-1");

        thread2.start();
    }


    private static class Result {

        private String result;

        //获取result，支持超时等待
        public synchronized String getResult(long mills) {
            try {
                long future = System.currentTimeMillis() + mills;
                long remain = mills;
                /**
                 * 这里使用循环目的：通过while循环判断在线程等待remain时间或者线程被别的线程唤醒了之后，再次判断result是否为null，
                 * 如果为null，再判断是否还需要进行线程等待(remain>0)，两者只要有一个条件不符合，就直接返回result。
                 */
                while (result == null && remain > 0) {
                    System.out.println(Thread.currentThread().getName() + "-开始等待，remain=" + remain);
                    wait(remain);
                    remain = future - System.currentTimeMillis();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("-->>result= " + result);
            return result;
        }

        //线程赋值（原子操作，无需加锁）
        public void setResult(String result) {
            this.result = result;
        }
    }
}


/**
 * 测试：i++和++i问题
 */
class Test {
    public static void main(String[] args) {
        //i++
        test();
        test2();

        //++i
        test3();
        test4();
    }

    public static void test() {
        int i = 0;
        //i先赋值，i再自增
        int j = i++;
        System.out.println(String.format("i=%d,j=%d", i, j));
    }

    public static void test2() {
        int i = 0;

        //等价理解：int j=i++
        int temp = i;
        i = i + 1;
        int j = temp;

        System.out.println(String.format("i=%d,j=%d", i, j));
    }


    public static void test3() {
        int i = 0;

        //i先自增，再赋值
        int j = ++i;

        System.out.println(String.format("i=%d,j=%d", i, j));
    }

    public static void test4() {
        int i = 0;

        i = i + 1;
        int j = i;

        System.out.println(String.format("i=%d,j=%d", i, j));
    }
}
